jacquardRefs

← snapshot

2544 bytes
"use client";

import { useRouter } from "next/navigation";
import { useState } from "react";
import { ApiError, api } from "@/lib/api";
import { isValidRefName } from "@/lib/validate";

export function BranchForm({ repo, refNames }: { repo: string; refNames: string[] }) {
  const router = useRouter();
  const [name, setName] = useState("");
  const [from, setFrom] = useState(refNames[0] ?? "");
  const [error, setError] = useState<string | null>(null);
  const [pending, setPending] = useState(false);

  const touched = name.length > 0;
  const valid = isValidRefName(name) && from !== "";

  async function submit() {
    setPending(true);
    setError(null);
    try {
      await api.branch(repo, name, from);
      setName("");
      router.refresh();
    } catch (e) {
      setError(e instanceof ApiError ? e.message : String(e));
    } finally {
      setPending(false);
    }
  }

  return (
    <div>
      <div className="jac-cols" style={{ marginTop: 14, alignItems: "flex-end" }}>
        <div className="jac-field" style={{ flex: "1 1 220px", marginTop: 0 }}>
          <label className="jac-label" htmlFor="branch-name">
            New ref
          </label>
          <input
            id="branch-name"
            className="jac-input"
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="feature/retry"
            aria-invalid={touched && !isValidRefName(name)}
          />
        </div>
        <div className="jac-field" style={{ flex: "1 1 160px", marginTop: 0 }}>
          <label className="jac-label" htmlFor="branch-from">
            From the head of
          </label>
          <select
            id="branch-from"
            className="jac-select"
            value={from}
            onChange={(e) => setFrom(e.target.value)}
          >
            {refNames.map((r) => (
              <option key={r} value={r}>
                {r}
              </option>
            ))}
          </select>
        </div>
        <button
          type="button"
          className="jac-btn"
          disabled={!valid || pending}
          onClick={submit}
        >
          {pending ? "Branching…" : "Branch"}
        </button>
      </div>
      {touched && !isValidRefName(name) ? (
        <p className="jac-hint jac-hint--error">
          Ref names: non-empty segments joined by /, no leading or trailing /, no
          . or .. segments.
        </p>
      ) : null}
      {error ? <div className="jac-error-box">{error}</div> : null}
    </div>
  );
}